package soundChaser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javazoom.jl.converter.Converter;
import javazoom.jl.converter.Converter.PrintWriterProgressListener;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.Equalizer;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.decoder.OutputChannels;
import javazoom.jl.player.Player;

public class WaveLesen
{

	private String mp3src;
	private long sampleRate = 0;

	/**
	 * Konstruktor
	 * 
	 * @param mp3Source
	 */
	public WaveLesen(String mp3Source)
	{
		this.mp3src = mp3Source;
	}

	/**
	 * Diese Methode schneidet die Dateiendung weg und ruft dann
	 * convert(dstPath) auf!
	 * 
	 * @return Der Path wo das Wave-File hingespeichert wurde.
	 */
	public String convert()
	{
		String dstPath;
		String pattern = ".";
		int punkt;

		punkt = mp3src.lastIndexOf(pattern);
		dstPath = mp3src.substring(0, punkt) + ".wav";

		convert(dstPath);
		return (dstPath);
	}

	/**
	 * Diese Methode wandelt die MP3 in eine WAV um und speichert diese auf der
	 * Festplatte.
	 * 
	 * @param dstPath
	 * @return Der Path wo das Wave-File hingespeichert wurde. Dies ist auch der
	 *         Übergabeparameter! Dies wurde gemacht, dass convert() und
	 *         convert(String) den gleichen Rückgabeparameter liefern.
	 */
	public String convert(String dstPath)
	{
		//if the path is the same, the original MP3 will be damaged
		if (!dstPath.equals(mp3src))
		{
			Converter myConverter = new Converter();

			// settings for always converting to a 2 channel wave file
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
			PrintWriterProgressListener pl = new PrintWriterProgressListener(
					pw, PrintWriterProgressListener.NO_DETAIL);
			Decoder.Params param = new Decoder.Params();
			param.setOutputChannels(OutputChannels.fromInt(2));

			try
			{
				myConverter.convert(mp3src, dstPath, pl, param);
			} catch (JavaLayerException e)
			{
				e.printStackTrace();
			}
			return dstPath;
		} else
			return null;
	}

	/**
	 * Wave umändern TODO Urspruengliche Quelle:
	 * http://www.labbookpages.co.uk/audio/javaWavFiles.html
	 * 
	 * @param wavPath
	 *            der Pfad zur WaveDatei
	 */
	public double[][] wave2array(String wavPath)
	{
		double[][] wertearray = null;

		try
		{
			// RAM benötigt: Bei Disturbed ca. 170MB
			// Die Wav-Datei muss immer 2 Channels haben, wegen dem 2D-Array

			// Open the wav file specified as the first argument
			WavFile wavFile = WavFile.openWavFile(new File(wavPath));

			// Display information about the wav file
			// wavFile.display();
			sampleRate = wavFile.getSampleRate();

			long zulesen = wavFile.getNumFrames();

			if (zulesen > Integer.MAX_VALUE)
			{
				System.out
						.println("SCHWERER FEHLER: Wave-File ist zu lange und passt nicht ins Wertearray!");
			} else
			{
				wertearray = new double[2][(int) zulesen];
			}

			// Get the number of audio channels in the wav file
			int numChannels = wavFile.getNumChannels();

			// Create a buffer of 100 frames
			double[] buffer = new double[100 * numChannels];

			int framesNowRead;
			int framesComplRead = 0;

			do
			{
				// Read frames into buffer
				framesNowRead = wavFile.readFrames(buffer, 100);

				// Frames auslesen und ins wertearray speichern
				// Gerades s ist 1.Channel, ungerades s ist 2.Channel
				for (int s = 0; s < framesNowRead * numChannels; s += 2)
				{
					wertearray[0][framesComplRead + (s / 2)] = buffer[s];
				}

				for (int s = 1; s < framesNowRead * numChannels; s += 2)
				{
					wertearray[1][framesComplRead + ((s - 1) / 2)] = buffer[s];
				}

				framesComplRead += framesNowRead;

			} while (framesNowRead != 0);

			// Close the wavFile
			wavFile.close();

		} catch (Exception e)
		{
			System.err.println(e);
		}

		return wertearray;
	}

	/**
	 * Erst nach wave2array aufrufen.
	 * 
	 * @return die SampleRate, mit der die WaveDatei kodiert ist (z. B. 44100
	 *         Hz)
	 */
	public long getSampleRate()
	{
		return sampleRate;
	}
}
